public class OtsuStat implements Stat {
  private float weightL, weightR, meanL, meanR;
  int thresh;

  public float getWeightL() {
    return this.weightL;
  }
  
  public float getWeightR() {
    return this.weightR;
  }
  
  public float getMeanL() {
    return this.meanL;
  }
  
  public float getMeanR() {
    return this.meanR;
  }
  
  public int getThresh() {
    return this.thresh;
  }
  
  public void setThresh(int t) {
    println("Warning: can't manually set threshold with Otsu's method");
  }
  
  public void process(float[] ps) {
    weightL = 0;      
    weightR = 0;
    meanL = 0;
    meanR = 0;
    thresh = 0;
    float wL = 0;
    float wR = 0;
    float sumL = 0;
    float sumR = 0;
    float varMax = 0;
    for (int i = 0; i < ps.length; i++) {
      wR += ps[i]; 
      sumR += i * ps[i];
    }
    for (int i = 0; i < ps.length; i++) {
      wL += ps[i];
      wR -= ps[i];
      float p = i * ps[i];
      sumL += p;
      sumR -= p;
      float mL = sumL / wL;
      float mR = sumR / wR;
      float varBetween = wL * wR * pow(mL - mR, 2);
      if (varBetween > varMax) {
        varMax = varBetween;
        weightL = wL;
        weightR = wR;
        meanL = mL;
        meanR = mR;
        thresh = i;
      }
    }
  }
}
  
